#pragma once
#ifndef _Camera_Header_included_
#define _Camera_Header_included_

#include <Engine/ICamera.h>
#include <Engine/IInputListener.h>
#include <Engine/Math/Plane3.h>

namespace fastbird
{
	class Camera : public ICamera, IInputListener
	{
	public:
		enum FRUSTUM_PLANE
		{
			FRUSTUM_PLANE_NEAR   = 0,
			FRUSTUM_PLANE_FAR    = 1,
			FRUSTUM_PLANE_LEFT   = 2,
			FRUSTUM_PLANE_RIGHT  = 3,
			FRUSTUM_PLANE_TOP    = 4,
			FRUSTUM_PLANE_BOTTOM = 5
		};

		Camera();
		~Camera();

		virtual void SetPos(const Vec3& pos) { mPos = pos; mViewPropertyChanged = true;}
		virtual const Vec3& GetPos() const { return mPos; } 
		virtual void SetDir(const Vec3& dir) { mDir = dir; mViewPropertyChanged = true;}
		virtual const Vec3& GetDir() const { return mDir; }
		virtual void SetCustomViewMat(const Mat44& viewMat) 
		{ 
			mCustomViewMat = viewMat;
			if (mUseCustomViewMat)
				mUseCustomViewMat = 2;
		}
		virtual void UseCustomViewMat(bool use) { use ? mUseCustomViewMat=2 : mUseCustomViewMat=0; }
		virtual const Mat44& GetViewMat();
		virtual const Mat44& GetViewProjMat();
		
		// field of view in the y direction, in radians.
		virtual void SetFOV(float fov) { mFov = fov; mProjPropertyChanged = true;}
		virtual float GetFOV() const { return mFov; }
		// width / height
		virtual void SetAspectRatio(float ar) { mAspectRatio = ar; mProjPropertyChanged = true;}
		virtual float GetAspectRatio() const { return mAspectRatio; }
		// near/far view-plane
		virtual void SetNearFar(float nearPlane, float farPlane);
		virtual void GetNearFar(float& nearPlane, float& farPlane) const;
		// width and height of the view volume at the near view-plane
		virtual void SetWidth(float width) { mWidth = width; mProjPropertyChanged = true;}
		virtual void SetHeight(float height) { mHeight = height; mProjPropertyChanged = true;}
		virtual float GetWidth() const { return mWidth; }
		virtual float GetHeight() const { return mHeight; }
		virtual void SetName(const char* name) { mName = name; }
		virtual const char* GetName() const { return mName.c_str(); }
		
		//--------------------------------------------------------------------
		// IInputListener
		//--------------------------------------------------------------------
		virtual void OnInput(IMouse* pMouse, IKeyboard* pKeyboard);

		virtual void Update();

		virtual bool IsCulled(BoundingVolume* pBV) const;

	protected:
		void UpdateFrustum();


	private:
		bool mViewPropertyChanged;
		bool mProjPropertyChanged;
		Mat44 mViewMat;
		Mat44 mCustomViewMat;
		int mUseCustomViewMat;
		Mat44 mProjMat;
		Mat44 mViewProjMat;
		Vec3 mPos;
		Vec3 mDir;
		float mFov;
		float mAspectRatio;
		float mNear;
		float mFar;
		float mWidth;
		float mHeight;
		std::string mName;
		Vec3 mUp;
		Vec3 mRight;
		bool mFixedUp;
		float mSpeed;
		Plane3 mPlanes[6];
		float mMouseSensitive;
	};
}

#endif //_Camera_Header_included_